home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ov143b.zip / OVVIEW.C < prev    next >
C/C++ Source or Header  |  1993-01-04  |  29KB  |  858 lines

  1. /*  034  23-May-87  ovview.c
  2.  
  3.         Copyright (c) 1987 by Blue Sky Software.  All rights reserved.
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <fcntl.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include "ov.h"
  11. #include "overr.h"
  12. #include "menu.h"
  13. #include "direct.h"
  14. #include "strmem.h"
  15.  
  16. #define H_bar (0xcd)
  17. #define V_bar (179)
  18. #define FSTR_LEN (40)                  /* max find str length */
  19.  
  20. #define Vnextch(fh) ((curp < endp) ? *curp++ : vnextch(fh))  /* speed up */
  21. #define Vprevch(fh) ((curp > bufp) ? *--curp : vprevch(fh))  /* buffer access */
  22.  
  23. extern unsigned char far *curp;                /* current char position */
  24. extern unsigned char far *bufp, far *endp;     /* buffer begin/end pointers */
  25.  
  26. static int (*mark_func)();             /* pointer to marker function */
  27. static int nlines;                     /* # lines displayed on screen */
  28. static unsigned char ascmode;          /* true means ascii mode display */
  29. static unsigned char bitmask;          /* for 7 or 8 bit display mode */
  30. static int inf;                        /* handle for file being viewed */
  31. static int margin;                     /* margin for right/left scrolling */
  32. static long tos;                       /* top of screen offset in file */
  33. static long markers[5];                /* marker positions  */
  34. static char *findstr = NULL;           /* string to find in view */
  35. static long findloc;                   /* offset of last find */
  36. static long hiline;                    /* offset of highlighted line */
  37. static int igncase = 1;                /* NZ if ignoring case in find */
  38.  
  39. /* function delcarations created by -Zg option - ALTCALL added
  40.    NOTE: anything called by menu routine cannot be ALTCALL */
  41.  
  42. void vfind(int);
  43. static int view_prev(void), view_tof(void), view_eof(void);
  44. int view(void), view_move(int), view_fignore(void), view_fexact(void);
  45. static int view_exit(void), view_down(void), view_up(void), view_next(void);
  46. static int view_right(void), view_left(void), view_set(void), view_goto(void);
  47. static int view_fnxt(void), view_fprv(void), view_fstr(void), view_fopt(void);
  48. static int do_mark(void), setmark(void), gomark(void), ALTCALL view_line(void);
  49. static int view_7bit(void), view_8bit(void), view_asc(void), view_hex(void);
  50.  
  51. static int ALTCALL nsol(void), ALTCALL more2view(void);
  52. static int ALTCALL align(void), ALTCALL backup(int), ALTCALL peol(void);
  53. static int ALTCALL fmt_asc_line(char *,int *), ALTCALL fmt_hex_line(char *,int *);
  54.  
  55. static struct key_ent {        /* table mapping movement keys to functions */
  56.    int key;
  57.    int (*func)();
  58. } key2func[] = { { DOWN, view_next }, { UP, view_prev }, { PGDN, view_down },
  59.    { PGUP, view_up }, { HOME, view_tof }, { END, view_eof },
  60.    { RIGHT, view_right }, { LEFT, view_left } };
  61.  
  62. #define NMOVKEYS (8)
  63.  
  64. extern MENU_STATE curmenu;
  65. extern MENU top_file_menu[], *top_menu;
  66.  
  67. static char setgo[] = "Set/Goto marker";
  68.  
  69. static MENU fopt_menu[] = {
  70.    { "Ignore", "Ignore case when searching", view_fignore, NULL },
  71.    { "Exact", "Match case of string when searching", view_fexact, NULL },
  72.    { NULL, NULL, NULL, NULL }
  73. };
  74.  
  75. static MENU find_menu[] = {
  76.    { "Next", "Find next occurance", view_fnxt, NULL },
  77.    { "Prev", "Find previous occurance", view_fprv, NULL },
  78.    { "String", "Set string to find", view_fstr, NULL },
  79.    { "Options", "Set find options", NULL, fopt_menu },
  80.    { NULL, NULL, NULL, NULL }
  81. };
  82.  
  83. static MENU mark_menu[] = {
  84.    { "1", setgo, do_mark, NULL },
  85.    { "2", setgo, do_mark, NULL },
  86.    { "3", setgo, do_mark, NULL },
  87.    { "4", setgo, do_mark, NULL },
  88.    { "5", setgo, do_mark, NULL },
  89.    { NULL, NULL, NULL, NULL }
  90. };
  91.  
  92. MENU top_view_menu[] = {
  93.    { "Dwn", "Page down in the file", view_down, NULL },
  94.    { "Up", "Page up in the file", view_up, NULL },
  95.    { "Nxt", "Advance one line", view_next, NULL },
  96.    { "Prv", "Backup one line", view_prev, NULL },
  97.    { "Rght", "Scroll right 8 characters", view_right, NULL },
  98.    { "Left", "Scroll left 8 characters", view_left, NULL },
  99.    { "TOF", "Goto Top Of File", view_tof, NULL },
  100.    { "EOF", "Goto End Of File", view_eof, NULL },
  101.    { "Set", "Set marker at current position", view_set, mark_menu },
  102.    { "Goto", "Goto set marker position", view_goto, mark_menu },
  103.    { "Find", "Find string", NULL, find_menu },
  104.    { "Asc", "Display file in ASCII", view_asc, NULL },
  105.    { "Hex", "Display file in hex", view_hex, NULL },
  106.    { "7b", "Display 7 bits per character", view_7bit, NULL },
  107.    { "8b", "Display 8 bits per character", view_8bit, NULL },
  108.    { "Quit", "Return to file display", view_exit, top_file_menu },
  109.    { NULL, NULL, NULL, NULL }
  110. };
  111.  
  112. extern WINDOW cw;
  113.        extern char *cantopen;
  114. extern FILE_ENT files[];
  115. extern unsigned char view_display, restricted;
  116.  
  117. int ALTCALL vbuf_init(int );           /* declarations for buffer routines */
  118. int ALTCALL vbuf_free(void);
  119. unsigned long ALTCALL vtell(void);
  120. int ALTCALL vseek(int ,long ), ALTCALL vnextch(int ), ALTCALL vprevch(int );
  121.  
  122. #define view_seek(off) vseek(inf,off)
  123.  
  124.  
  125. /******************************************************************************
  126.  **                             V I E W                                      **
  127.  *****************************************************************************/
  128.  
  129. view() {               /* view the current file at the terminal */
  130.  
  131.    int i;
  132.    register char *fn;
  133.    register FILE_ENT *fp;
  134.  
  135.    /* don't try to view file if its empty */
  136.  
  137.    fp = &files[cw.curidx];             /* a couple of quick pointers */
  138.  
  139.    if (fp->size == 0)
  140.       show_error(0,EMPTY_FILE,1,"This file is empty!");
  141.  
  142.    bitmask = 0xff;             /* defaults: 8 bit, ascii, left edge */
  143.    ascmode = TRUE;
  144.    margin = 0;
  145.  
  146.    /* open the file to be viewed, error out if can't open */
  147.  
  148.    if ((inf = open((fn = fname(fp)),O_RDONLY|O_BINARY)) == -1) {
  149.       free(fn);
  150.       show_error(SHOW_DOS,CANT_OPEN,3,cantopen,fp->name,": ");
  151.    }
  152.  
  153.    savescreen();               /* save current display image */
  154.    restricted = TRUE;          /* disable special file commands */
  155.    view_display = TRUE;        /* yes, we are viewing */
  156.  
  157.    for (i = 0; i < 5; i++)     /* set markers to TOF */
  158.       markers[i] = 0L;
  159.  
  160.    hiline = findloc = -1L;     /* indicate no finds/no highlighted lines yet */
  161.  
  162.    vbuf_init(inf);             /* initialize view buffer system */
  163.  
  164.    center_text(FIRST_VROW-1,fn); /* show file name */
  165.    free(fn);
  166.  
  167.    view_down();                /* display the first screen of file data */
  168.  
  169.    top_menu = top_view_menu;   /* setup the view menu as the main menu */
  170. }
  171.  
  172.  
  173. /******************************************************************************
  174.  **                        V I E W _ E X I T                                 **
  175.  *****************************************************************************/
  176.  
  177. static int
  178. view_exit() {          /* exit the view display, return to file display */
  179.  
  180.    close(inf);                 /* close file */
  181.    vbuf_free();                /* release memory */
  182.    top_menu = top_file_menu;   /* restore file menu as main */
  183.  
  184.    restricted = FALSE;         /* all commands are enabled */
  185.    view_display = FALSE;       /* not viewing */
  186.  
  187.    restorescreen();            /* redisplay prior screen image */
  188. }
  189.  
  190.  
  191. /******************************************************************************
  192.  **                        V I E W _ D O W N                                 **
  193.  *****************************************************************************/
  194.  
  195. static int
  196. view_down() {          /* page down into the view buffer/file */
  197.  
  198.    register int i;
  199.  
  200.    if (!more2view())           /* nothing to do if no more data to view */
  201.       return;
  202.  
  203.    nlines = 0;                 /* no lines displayed yet */
  204.    tos = vtell();              /* remember where top of screen is */
  205.  
  206.    /* display up to a screen full of file data, clear the screen as we go */
  207.  
  208.    for (i = 0; i < VIEW_ROWS; i++) {
  209.       gotorc(i+FIRST_VROW,0);          /* position to line */
  210.       if (view_line())                 /* display a single line */
  211.          nlines++;                     /* count lines displayed */
  212.    }
  213. }
  214.  
  215.  
  216. /******************************************************************************
  217.  **                        V I E W _ U P                                     **
  218.  *****************************************************************************/
  219.  
  220. static int
  221. view_up() {            /* page up into the view buffer */
  222.  
  223.    long curoff;
  224.  
  225.    /* back two screen's worth, or to the top line in memory and use
  226.       view_down() to display the screen - only display if we really
  227.       backed up (might be at TOF) */
  228.  
  229.    curoff = vtell();                   /* where we were */
  230.    view_seek(tos);                     /* quickly to top of screen */
  231.    if (backup(VIEW_ROWS))              /* try to backup another screen */
  232.       view_down();                     /* display prior screen if backed up */
  233.    else
  234.       view_seek(curoff);               /* must be tof, back to where we were */
  235. }
  236.  
  237.  
  238. /******************************************************************************
  239.  **                        V I E W _ N E X T                                 **
  240.  *****************************************************************************/
  241.  
  242. static int
  243. view_next() {          /* display the next line in the buffer/file */
  244.  
  245.    long curoff;
  246.  
  247.    if (!more2view())           /* nothing to do if no more data to view */
  248.       return;
  249.  
  250.    /* set the new top of screen location */
  251.  
  252.    if (ascmode) {                      /* ascii mode display? */
  253.       curoff = vtell();                /* save where we are */
  254.       view_seek(tos);                  /* to top of screen  */
  255.       nsol();                          /* to start of next line */
  256.       tos = vtell();                   /* its the new top of screen */
  257.       view_seek(curoff);               /* back to bottom of screen */
  258.  
  259.    } else                              /* hex mode */
  260.      tos += 16;                        /* tos is just the next hex line */
  261.  
  262.    /* scroll the screen up one line to make room for the new line at bottom */
  263.  
  264.    delete_line(FIRST_VROW,VIEW_ROWS-1);
  265.  
  266.    gotorc(FIRST_VROW+VIEW_ROWS-1,0);   /* cursor to the last display line */
  267.  
  268.    view_line();                        /* display the line */
  269. }
  270.  
  271.  
  272. /******************************************************************************
  273.  **                        V I E W _ P R E V                                 **
  274.  *****************************************************************************/
  275.  
  276. static int
  277. view_prev() {          /* display the previous line in the buffer */
  278.  
  279.    long curoff;
  280.  
  281.    curoff = vtell();                   /* where we are now */
  282.    view_seek(tos);                     /* old top of screen */
  283.    if (backup(1)) {                    /* can we backup another line */
  284.       tos = vtell();                           /* if so, its new tos */
  285.       insert_line(FIRST_VROW+1,VIEW_ROWS-1);   /* insert a blank line */
  286.       gotorc(FIRST_VROW,0);                    /* cursor to first line */
  287.       view_line();                             /* display the line */
  288.       view_seek(curoff);                       /* back to old bottom */
  289.       if (nlines < VIEW_ROWS)                  /* is a full screen displayed? */
  290.          nlines++;                             /* no, one more displyed now */
  291.       else
  292.          backup(1);                            /* yes, back one line */
  293.  
  294.    } else                      /* couldn't backup, must be tof */
  295.       view_seek(curoff);
  296. }
  297.  
  298.  
  299. /******************************************************************************
  300.  **                        V I E W _ T O F                                   **
  301.  *****************************************************************************/
  302.  
  303. static int
  304. view_tof() {           /* backup and display the top of the file */
  305.  
  306.    view_seek(0L);              /* just go to top of file */
  307.    view_down();                /* and display a screen */
  308. }
  309.  
  310.  
  311. /******************************************************************************
  312.  **                        V I E W _ E O F                                   **
  313.  *****************************************************************************/
  314.  
  315. static int
  316. view_eof() {           /* display the end of the file */
  317.  
  318.    view_seek(files[cw.curidx].size);       /* seek to eof */
  319.    backup(VIEW_ROWS);                      /* backup a screen full */
  320.    view_down();                            /* display a screen full */
  321. }
  322.  
  323.  
  324. /******************************************************************************
  325.  **                        V I E W _ M O V E                                 **
  326.  *****************************************************************************/
  327.  
  328. view_move(mov_cmd)     /* move around the view buffer/file in response to */
  329. int mov_cmd;           /* single key commands when viewing a file */
  330. {
  331.  
  332.    register int i;
  333.  
  334.    /* basically, we just map the special keys to the same functions
  335.       performed by the menu options */
  336.  
  337.    for (i = 0; i < NMOVKEYS; i++)
  338.       if (mov_cmd == key2func[i].key) {
  339.          (*key2func[i].func)();
  340.          break;
  341.       }
  342. }
  343.  
  344.  
  345. /*****************************************************************************
  346.                  V I E W _ S E T / G O T O / M A R K
  347.  *****************************************************************************/
  348.  
  349. static int
  350. view_set() {           /* prepare to set a marker to current position */
  351.  
  352.    mark_func = setmark;        /* use the setmark routine later */
  353. }
  354.  
  355. static int
  356. view_goto() {          /* prepare to goto a marker position */
  357.  
  358.    mark_func = gomark;         /* use the gomark routine later */
  359. }
  360.  
  361. static int
  362. do_mark() {            /* set or goto a marker position */
  363.  
  364.    (*mark_func)();
  365. }
  366.  
  367. static int
  368. setmark() {            /* set a marker position */
  369.  
  370.    markers[curmenu.current_selection] = tos;
  371. }
  372.  
  373. static int
  374. gomark() {             /* goto a marker position */
  375.  
  376.    tos = markers[curmenu.current_selection];   /* where tos should be */
  377.    align();                                    /* start at begining of line */
  378.    view_down();                                /* display screen full */
  379. }
  380.  
  381.  
  382. /*****************************************************************************
  383.              V I E W _ F N X T / P R V / I G N O R E / E X A C T
  384.  *****************************************************************************/
  385.  
  386. static int
  387. view_fnxt() {          /* find the string in forward direction */
  388.  
  389.    vfind(1);           /* 1 means search forward */
  390. }
  391.  
  392. static int             /* find the string in backward direction */
  393. view_fprv() {
  394.  
  395.    vfind(0);           /* 0 means search backward */
  396. }
  397.  
  398. static int             /* ignore case */
  399. view_fignore() {
  400.  
  401.    igncase = 1;
  402. }
  403.  
  404. static int              /* require exact case match */
  405. view_fexact() {
  406.  
  407.    igncase = 0;
  408. }
  409.  
  410.  
  411. /**************************************************************************
  412.                                V F I N D
  413.  **************************************************************************/
  414.  
  415. void
  416. vfind(forward)     /* find a string in selected direction */
  417. register int forward;
  418. {
  419.  
  420.    int fch;
  421.    long temploc;
  422.    register int ch;
  423.    char *fcp, nfmsg[11+FSTR_LEN];
  424.  
  425.    if (findstr == NULL)
  426.       show_error(0,NO_FND_STR,1,"No find string has been selected");
  427.  
  428.    /* pick where to start the search from - if this is the first find or the
  429.       last find location isn't currently displayed, start from the tos (if
  430.       going forward) or bottom of screen (if going backward) - otherwise,
  431.       start 1 character offset from the last find so we don't find the same
  432.       string again. */
  433.  
  434.    if (findloc < 0L || findloc < tos || findloc >= vtell())
  435.       findloc = forward ? tos : vtell();
  436.  
  437.    else        /* its on the screen - try to offset by 1 */
  438.  
  439.       if (forward && findloc < files[cw.curidx].size)  /* going forward */
  440.          findloc++;
  441.       else
  442.          if (!forward && findloc > 0L)                 /* going backward */
  443.             findloc--;
  444.  
  445.    view_seek(findloc);                 /* move to 1st/last find location */
  446.  
  447.    /* try to find users string in file */
  448.  
  449.    fch = *findstr;                     /* first char in find string */
  450.  
  451.    while ((ch = forward ? Vnextch(inf) : Vprevch(inf)) != EOF)
  452.  
  453.       /* is this the first char of the search string? */
  454.  
  455.       if (ch == fch || igncase && tolower(ch) == tolower(fch)) {
  456.  
  457.          temploc = vtell();    /* could be it, remember where we are */
  458.  
  459.          /* does the rest of the string match? */
  460.  
  461.          if (!forward)         /* adjust if we are searching backward */
  462.             vnextch(inf);
  463.  
  464.          for (fcp = findstr+1; *fcp; fcp++)    /* check rest of string */
  465.             if ((ch = vnextch(inf)) != *fcp)
  466.                if (!igncase || tolower(ch) != tolower(*fcp))
  467.                   break;;
  468.  
  469.          if (*fcp == '\0')             /* ***** FOUND IT ***** */
  470.             break;
  471.  
  472.          view_seek(temploc);           /* not yet, back to where we were */
  473.       }
  474.  
  475.    if (ch == EOF) {                    /* EOF if wasn't found       */
  476.  
  477.       findloc = hiline = -1L;          /* don't highlight any lines */
  478.       strcpy(nfmsg,"Not found: ");     /* tell user it wasn't found */
  479.       strcat(nfmsg,findstr);
  480.       show_error(QUIET,0,1,nfmsg);
  481.       view_current();                  /* make sure no highlighted line */
  482.  
  483.    } else {                    /* ******* F O U N D   I T ******** */
  484.  
  485.       tos = findloc = temploc - forward;/* remember where string is */
  486.       align();                          /* goto start of that line  */
  487.       hiline = vtell();                 /* highlight this line      */
  488.       backup(VIEW_ROWS >> 1);           /* try to center line w/str */
  489.       view_down();                      /* view screen              */
  490.    }
  491. }
  492.  
  493. /***************************************************************************
  494.                             V I E W _ F S T R
  495.  ***************************************************************************/
  496.  
  497. static int
  498. view_fstr() {          /* pick the string to find */
  499.  
  500.    char *str;
  501.  
  502.    str = prompt("Select Find String","Enter string to find: ",findstr,0,FSTR_LEN);
  503.    if (strlen(str) == 0)
  504.       return;
  505.  
  506.    if (findstr)                /* release old find string */
  507.       free(findstr);
  508.  
  509.    findstr = Strdup(str);      /* make local copy of string */
  510.  
  511. }
  512.  
  513.  
  514. /*****************************************************************************
  515.                            V I E W _ L I N E
  516.  *****************************************************************************/
  517.  
  518. static int ALTCALL
  519. view_line() {          /* display a single line of the file */
  520.  
  521.    int col, ch, hl = 0;
  522.    char line[SCREEN_COLS+1];
  523.  
  524.    if (hl = (hiline == vtell()))       /* highlight this line if desired */
  525.       setvattrib(DIS_HIGH);
  526.  
  527.    if (ascmode)                        /* format line as ascii or hex data */
  528.       ch = fmt_asc_line(line,&col);
  529.    else
  530.       ch = fmt_hex_line(line,&col);
  531.  
  532.    disp_str(line);                     /* make one call to display line */
  533.  
  534.    if (col < margin+SCREEN_COLS)       /* clear if < full line displayed */
  535.       clr_eol();
  536.  
  537.    if (hl)                             /* alwasy go back to normal */
  538.       setvattrib(DIS_NORM);
  539.  
  540.    return(ch != EOF || col);   /* return true if something displayed */
  541. }
  542.  
  543.  
  544. /*****************************************************************************
  545.                          F M T _ A S C _ L I N E
  546.  ****************************************************************************/
  547.  
  548. static int ALTCALL
  549. fmt_asc_line(op,colp)  /* format an ascii line for display */
  550. char *op;
  551. int *colp;
  552. {
  553.    register int ch, col = 0;
  554.    int i, endcol = margin + SCREEN_COLS;
  555.  
  556.    while ((ch = Vnextch(inf)) != EOF && (ch = ch & bitmask) != '\n')
  557.       if (ch == '\t') {
  558.          for (i = 8 - (col & 7); i; i--, col++)
  559.             if (col >= margin && col < endcol)
  560.                *op++ = ' ';
  561.        } else
  562.           if (ch != '\r' && ch != '\0') {
  563.               if (col >= margin && col < endcol)
  564.                   *op++ = ch;
  565.              col++;
  566.           }
  567.  
  568.    *op = '\0';                 /* null terminate it for disp_str */
  569.  
  570.    *colp = col;                /* tell caller the # cloumns */
  571.    return(ch);                 /* and if EOF was reached */
  572. }
  573.  
  574.  
  575. /******************************************************************************
  576.                           F M T _ H E X _L I N E
  577.  *****************************************************************************/
  578.  
  579. static int ALTCALL
  580. fmt_hex_line(op,colp)  /* format a hex line for later display */
  581. register char *op;
  582. int *colp;
  583. {
  584.    int ch, ach, j;
  585.    register int i;
  586.    char offstr[9], *ap;
  587.    static char bin2hex[] = "0123456789ABCDEF";
  588.  
  589.    /* test if there is anything to format */
  590.  
  591.    if (vnextch(inf) == EOF) {
  592.       *colp = 0;
  593.       *op = '\0';
  594.       return(EOF);
  595.    } else
  596.       vprevch(inf);
  597.  
  598.    /* format data offset into buffer */
  599.  
  600.    ultoa(vtell(),offstr,16);           /* offset to hex */
  601.    j = strlen(offstr);
  602.    for (i = 6 - j; i > 0; i--)         /* zero fill */
  603.       *op++ = '0';
  604.    if (j <= 6)                         /* don't use more than 6 digits */
  605.      strcpy(op,offstr);
  606.    else
  607.      strcpy(op,offstr+j-6);
  608.  
  609.    strupr(op);                         /* ultoa leaves A-F in lower case */
  610.  
  611.    strcat(op,"  ");                    /* go beyond the offset */
  612.    op += strlen(op);
  613.  
  614.    ap = op + 53;                       /* where ascii data starts */
  615.    *ap++ = V_bar;                      /* might as well do it now */
  616.  
  617.    /* setup data in hex (and ascii) */
  618.  
  619.    for (i = 16; i; i--) {              /* at most 16 bytes to fmt */
  620.  
  621.       ch = Vnextch(inf);               /* next char from file */
  622.       if (ch == EOF)                   /* done? */
  623.          break;
  624.  
  625.       *op++ = bin2hex[(ch >> 4) & 0x0f];       /* hexalate it */
  626.       *op++ = bin2hex[ch & 0x0f];
  627.       *op++ = ' ';
  628.  
  629.       if (((i+3) & 3) == 0)            /* extra spacer every 4 bytes */
  630.          *op++ = ' ';
  631.  
  632.       if ((ach = ch & bitmask) < ' ')  /* do the ascii char, '.' if ctrl ch */
  633.          *ap++ = '.';
  634.       else
  635.          *ap++ = ach;
  636.    }
  637.  
  638.    /* blank fill if EOF was reached */
  639.  
  640.    for ( ; i; i--) {           /* i is # chars to blank fill */
  641.       strncpy(op,"   ",3);
  642.       op += 3;
  643.       if (((i+3) & 3) == 0)
  644.          *op++ = ' ';
  645.       *ap++ = ' ';
  646.    }
  647.  
  648.    *op++ = ' ';                /* up to ascii data */
  649.  
  650.    *ap++ = V_bar;              /* closing bar at end */
  651.    *ap = '\0';                 /* The Terminator */
  652.  
  653.    *colp = 74;                 /* tell call how many columns */
  654.    return(ch);                 /* and if EOF was reached */
  655. }
  656.  
  657.  
  658. /*****************************************************************************
  659.                       V I E W _ R I G H T / L E F T
  660.  *****************************************************************************/
  661.  
  662. static int
  663. view_right() {         /* scroll right 8 characters */
  664.  
  665.    margin += 8;
  666.    view_current();
  667.    disp_margin();
  668. }
  669.  
  670. static int
  671. view_left() {          /* scroll left 8 characters */
  672.  
  673.    if (margin >= 8) {
  674.       margin -= 8;
  675.       view_current();
  676.       disp_margin();
  677.    }
  678. }
  679.  
  680. static int
  681. disp_margin() {        /* display the viewing margins */
  682.  
  683.    char marstr[11];
  684.  
  685.    if (margin) {
  686.  
  687.       itoa(margin,marstr,10);
  688.       disp_msg(2,"COL: ",marstr);
  689.  
  690.    } else              /* must have just gone to 0 */
  691.  
  692.       clr_msg();
  693. }
  694.  
  695.  
  696. /*****************************************************************************
  697.                             V I E W _ n B I T
  698.  *****************************************************************************/
  699.  
  700. static int
  701. view_7bit() {          /* display data using low order 7 bits */
  702.  
  703.    if (bitmask != 0x7f) {
  704.       bitmask = 0x7f;
  705.       view_current();
  706.    }
  707. }
  708.  
  709. static int
  710. view_8bit() {          /* display data using all 8 bits per char */
  711.  
  712.    if (bitmask != 0xff) {
  713.       bitmask = 0xff;
  714.       view_current();
  715.    }
  716. }
  717.  
  718. static int
  719. view_current() {       /* redisplay the current screen */
  720.  
  721.       view_seek(tos);
  722.       view_down();
  723. }
  724.  
  725.  
  726. /*****************************************************************************
  727.                            V I E W _ A S C
  728.  *****************************************************************************/
  729.  
  730. static int
  731. view_asc() {           /* set ascii mode display */
  732.  
  733.    if (!ascmode) {                    /* only need to change if in hex mode */
  734.       ascmode = TRUE;                 /* set ascii mode */
  735.       align();                        /* make sure were at begining of line */
  736.       view_down();                       /* redisplay in ascii format */
  737.    }
  738. }
  739.  
  740.  
  741. /*****************************************************************************
  742.                           V I E W _ H E X
  743.  *****************************************************************************/
  744.  
  745. static int
  746. view_hex() {           /* set hex mode display */
  747.  
  748.    if (ascmode) {                     /* only need to change if in ascii mode */
  749.       ascmode = FALSE;                /* set hex mode */
  750.       align();                        /* make sure were at begining of line */
  751.       view_down();                    /* redisplay in ascii format */
  752.    }
  753. }
  754.  
  755.  
  756. /*****************************************************************************
  757.                                 A L I G N
  758.  *****************************************************************************/
  759.  
  760. static int ALTCALL
  761. align() {              /* align tos to be at the start of a line */
  762.  
  763.    if (ascmode) {              /* ascii mode? */
  764.  
  765.       view_seek(tos);                 /* backup to current top of screen */
  766.       if (backup(1))                  /* make sure were at the start of */
  767.          nsol();                      /*   the current line */
  768.  
  769.    } else {                    /* hex mode */
  770.  
  771.       tos &= ~((long) 0x0f);          /* force a paragraph boundry */
  772.       view_seek(tos);                 /* backup to current top of screen */
  773.    }
  774. }
  775.  
  776. /*****************************************************************************
  777.                                 B A C K U P
  778.  *****************************************************************************/
  779.  
  780. static int ALTCALL
  781. backup(todo)           /* backup todo lines from current position */
  782. int todo;
  783. {
  784.    register int i;
  785.    int part, bytes;
  786.    unsigned long off, lines;
  787.  
  788.     /* backup in hex mode */
  789.  
  790.     if (!ascmode) {                    /* different if in hex mode */
  791.        off = vtell();                  /* current loc in file */
  792.        lines = off >> 4;               /* # full hex display lines above */
  793.        part = (bytes = off & (long) 0x0f) > 0; /* may be partial line if at eof */
  794.        if (todo > lines + part) {              /* more todo than are? */
  795.           view_seek(0L);                       /* just goto tof */
  796.           return(lines + part);                /* went back this # lines */
  797.        } else {
  798.           view_seek(off - (((todo - part) << 4)+bytes)); /* backup todo lines */
  799.           return(todo);
  800.        }
  801.     }
  802.  
  803.     /* backup in ascii mode */
  804.  
  805.     /* special case backing up from EOF - there may or may not be a \n
  806.        at the end of the last line */
  807.  
  808.     if (vnextch(inf) == EOF) {         /* at end of file? */
  809.        vprevch(inf);                   /*   always backup at least one char */
  810.        i = 1;                          /*   we will backup 1 line here      */
  811.        if (peol() == '\n')             /*   goto start of prev line         */
  812.           vnextch(inf);
  813.     } else {           /* not at EOF, setup for loop down below */
  814.        i = 0;
  815.        vprevch(inf);
  816.     }
  817.  
  818.     /* backup todo ascii lines, 1 line may have been done above */
  819.  
  820.     for ( ; i < todo; i++) {
  821.       if (peol() == EOF)               /* goto end of prev line */
  822.          break;
  823.       if (peol() == '\n')              /* end of prev prev line */
  824.          vnextch(inf);                 /* start of prev line    */
  825.    }
  826.  
  827.    return(i);          /* tell caller how many ascii lines backed up */
  828. }
  829.  
  830. static int ALTCALL
  831. peol() {       /* move to end of prev line */
  832.  
  833.    register int ch;
  834.  
  835.    while ((ch = Vprevch(inf)) != '\n' && ch != EOF) ;  /* end of prev line */
  836.    return(ch);
  837. }
  838.  
  839. static int ALTCALL
  840. nsol() {       /* move to start of next line */
  841.  
  842.    register int ch;
  843.  
  844.    while ((ch = Vnextch(inf)) != '\n' && ch != EOF) ;  /* start of next line */
  845.    return(ch);
  846. }
  847.  
  848.  
  849. /*****************************************************************************
  850.                             M O R E 2 V I E W
  851.  *****************************************************************************/
  852.  
  853. static int ALTCALL
  854. more2view() {          /* return true if more data to view */
  855.  
  856.    return(vtell() < files[cw.curidx].size);
  857. }
  858.